#!/usr/bin/env python
import getopt
import sys
import ConfigParser
import MySQLdb
import cPickle
sys.path.append('../../sincronizacion/')
sys.path.append('../Database')
from ClinicHistory import *
from Person import *
from Soap import *
from Sincronizacion import *  
from M2Crypto import SSL as SSL_LIB
import payFile
import ConnectionDB as conn
from proccesingQuery import DesingQuery 

HOST = '127.0.0.1'
PORT = 5050
BACKLOG = 5
BUFF_SIZE = 1024

SSL_PATH = 'certificados/'

SSL_VERSION = 'sslv3'
SSL_CERT_CLI = 'certificado-cliente.pem'
SSL_KEY_CLI = 'clave-cliente.pem'
SSL_CERT_AUTH = 'CAXplotacert.pem'

SERVER = 1
CLIENT = 0
XML_SOURCE = '../XML/'
BD_CONFIG = '../../modules/sincronizacion/settings_client.ini'

class SSL:
	""" Objeto que me proporciona
		la conexion segura con SSL"""

	def __init__(self):
		self.ssl_path = SSL_PATH
		self.ssl_version = SSL_VERSION
		self.ssl_cert_cli = SSL_CERT_CLI
		self.ssl_key_cli = SSL_KEY_CLI
		self.ssl_cert_auth = SSL_CERT_AUTH

	def context(self):
		con = SSL_LIB.Context(self.ssl_version)
		con.load_cert(certfile = self.ssl_path + self.ssl_cert_cli, 
				keyfile = self.ssl_path + self.ssl_key_cli,
				callback = self.pp_callback)
		con.load_verify_locations(self.ssl_path + self.ssl_cert_auth)
		con.set_verify(SSL_LIB.verify_peer | 
				SSL_LIB.verify_fail_if_no_peer_cert, depth = 9)
		return con

	def pp_callback(self, *args):
	# The passpharase is '0987'.
		return '18040808'

class Client:
	""" Objeto que me proporciona
		la conexion con el Servidor 
		GRIDEX """

	def __init__(self, con):
		self.host = HOST
		self.port = PORT
		self.backlog = BACKLOG
		self.buff_size = BUFF_SIZE
		self.con = con

	def conect(self):
		c = SSL_LIB.Connection(self.con)
		try:
			c.connect((self.host,self.port))
			if c.get_peer_cert() is not None:
				print "Cliente: Certificado del Servidor Correcto"
				self.conexion = c
			else:
				print "Cliente: No se pudo validar el Certificado"
				exit(2)
		except:
			print "Servidor no disponible"

	def send(self, data):
		len_data = cPickle.dumps(len(data))
		lenn = len(data)
		self.conexion.send(len_data)
		i = 0
		while lenn > 0:
			self.conexion.send(cPickle.dumps(data[i]))
			i += 1
			lenn -= 1
	
	def recv(self):
		data = self.conexion.read()
		len_info = 0
		if len(data) != 0:
			len_info = cPickle.loads(data)
		list = []
		while len_info > 0:
			data = self.conexion.read()
			list.append(cPickle.loads(data))
			len_info -= 1
		return list

	def recv_ex(self):                                                      
		data = self.conexion.read()
		len_info = 0
		if len(data) != 0:
			len_info = cPickle.loads(data)
		list = []
		while len_info > 0:
			list_temp = []
			tam = self.conexion.read()
			tam = cPickle.loads(tam)
			while tam > 0:
				data = self.conexion.read()
				list_temp.append(cPickle.loads(data))
				tam -= 1
			list.append(tuple(list_temp))
			len_info -= 1
		return list

	def recv_message(self):
		data = self.conexion.read()
		return data

	def send_message(self,string):
		self.conexion.send(string)	

	def close(self):
		self.conexion.close()

		
def reciving(cli):
	data = cli.recv_message()
	if data == "0":
		return 0
	else:
		return 1

def sending(cli,list):
	cli.send_message(list)


def find(fle):
	return payFile.findFile(fle,XML_SOURCE)

def uso():
	print "client_request.py -i <xml>"	

if __name__ == "__main__":

	try:
		opts, args = getopt.getopt(sys.argv[1:], "hi:v", ["help", "input_xml=", "output="])
	except getopt.GetoptError, err:
		print str(err)
		uso()
		exit(2)
	num_args = 0
	xml_input = None
	verbose = False
	for o, a in opts:
		if o == "-v":
			verbose = True
		elif o in ("-h", "--help"):
			uso()
			exit()
		elif o in ("-i", "--input_xml"):
			xml_input = a
			num_args = num_args + 1
		else:
			assert False, "Opci\xc3n desconocida".encode('latin-1')

	if not num_args == 1:
		print "El numero de parametros de entrada es incorrecto"
		uso()
		exit(2)

	ssl = SSL()
	context = ssl.context()
	client = Client(context)
	client.conect()
	
	if len(sys.argv) > 1:
		sending(client,sys.argv[2])
		root = find(sys.argv[2])
		if not reciving(client):
			print "Archivo no encontrado en el Servidor"	
		if root != None:
			design = DesingQuery(root,CLIENT)
 			#Conexion a la base de datos
			connection  = conn.connectionDB(root)
			connect = connection.connect()
			numberColumns = design.numberColumns().next()           #campo que indica operacion realizada
			for query in design.querySelectForTable():
				list_row = connection.executeSelectQuery(query,connect)
				client.send(list_row)
				fields = design.getFields().next()
				for row in list_row:
					connection.executeQuery(design.querySynchronized(row,fields),connect)
			
# Recibiendo registros con conflicto
			reciving(client)		
			if (reciving(client)):
				print "Existe conflicto entre varios registros"
				rowConflict = client.recv()
				for row in rowConflict:
					connection.executeQuery(design.queryConflict(row,fields),connect)
			else:
				print "No existe conflicto entre registros"
# Recibiendo registros cambiados en el servidor
			

			if (reciving(client)):
				print "Recibiendo registros a sincronizar desde el servidor"
				rowServer = client.recv()
				for row in rowServer:
					if  row[numberColumns] == 'I':
						operation =  design.insertQuery(row,fields)
					else:
						operation = design.updateQuery(row,fields)
					connection.executeQuery(operation,connect)
					connection.executeQuery(design.querySynchronized(row,fields),connect)
					
			else:
				print "No existen registros a sincronizar desde el servidor"
						
	
